/*********************************************************************
* FileName    : console.c
* Dependencies: 
* Processor   : PIC24F
* Complier    : Microchip C30 ,MPLAB IDE v8.90 or higher
* Company     : .
*
* Software License Agreement
*
*
*
* Author : Lau
* Date   : 7/8/2014
********************************************************************/

#include "console.h"
#include "fifo.h"
//#include <stdlib.h>
#include "ucos_ii.h"
#include "bsp.h"
//#include "channel_01.h"

/*
*********************************************************************************************************
*                                                CONSTANTS
*********************************************************************************************************
*/
//#define MSG_QUEUE_SZ	7					// MSG queue storage size
#define CMD_MAX_LEN		256					// 
#define U1R_BUF_LEN		64					// 
#define LF_N_CHAR		'\n'				//
#define CR_R_CHAR		'\r'				// CMD string ended with char CR_R_CHAR
#define BS_CHAR			'\x08'				// Backspace CHAR
#define DEL_CHAR		'\x7F'				// DELETE CMD CHAR
#define US_CHAR			'\x1F'				// Unit seperate char
#define ESC_CHAR		'\x1B'				// Escape
#define CMPL_CHAR		'\x5B'				// Complex cmd
#define CMPL_U_CHAR		'\x41'				// UP Key
#define CMPL_D_CHAR		'\x42'				// DOWN Key
#define CMPL_L_CHAR		'\x43'				// LEFT Key
#define CMPL_R_CHAR		'\x44'				// RIGHT Key

/*
*********************************************************************************************************
*                                                VARIABLES
*********************************************************************************************************
*/
USR_INT08U	CmdBuf[CMD_MAX_LEN];			// cmd string buffer
USR_INT08U	U1RxBuf[U1R_BUF_LEN];			// buffer
USR_INT08U	*pCmdCur;
USR_INT16S	ret_ctr, CmdSize;
//USR_INT32U	reg_valu;
//USR_INT08U	reg_addr;
//USR_FP32	freq;
//USR_INT08U	reg_valu_str[8];
//void *msg_q[MSG_QUEUE_SZ];
extern OS_EVENT *consol_q;

struct complexkey{
	union{
		USR_INT08U Byte;
		struct{
			USR_INT08U _1B:1;
			USR_INT08U _5B:1;
			USR_INT08U unused:6;
		};
	};
}compkey;
/*
struct CMDLIST{
	USR_INT08U	*p_arg;
	struct CMDLIST *p_n;
}arg[5];
*/
/*
*********************************************************************************************************
*                                            FUNCTION PROTOTYPES
*********************************************************************************************************
*/
static void ArrangeCMD(USR_INT16S lCtr);
//static void ExecCmd(void);

//static USR_INT16S uart1_send_data(const USR_CHAR *dat, USR_INT08U len);
//static inline void echo_char(const USR_CHAR lch);
//static inline void echo_str(const USR_CHAR *lstr, USR_INT08U len);

//static USR_INT16S rul_check(const USR_INT08U *lptr, CHECKRULE lrule);
//static void to_upper(USR_INT08U *lptr);
//static USR_INT32U hstr2i(const USR_INT08U *lptr);
//static void i2hstr(const USR_INT32U dat, USR_INT08U *ldst);
static void mov_block_r(USR_INT08U *lcur);
static void mov_block_l(USR_INT08U *lcur);

/*********************************************************************
 * Name        : void ConslTask(void *p_arg)
 * Function    : console task entry
 * PreCondition: None
 * Input       : p_arg unused
 * Output      : None
 * Side Effects: None
 * Author      : Lau
 * Time/Creat  : 15:50 7/8/2014
 * Time/Modify : 15:50 7/8/2014
 * Note        : Death loop, no return
 ********************************************************************/
void ConslTask(void *p_arg)
{
	
	(void)p_arg;
	FIFO_Init();			// initial uart fifo buffer
//	U1RXI_EN();				// enable uart interrupt
//	U1STAbits.URXDA = 0;
//	IFS0bits.U1TXIF = 0;				// Clear interrupt flag
//	IFS0bits.U1RXIF = 0;				// Clear interrupt flag
	IEC0bits.U1RXIE = 1;				// Enable UART1 RX interrupt
//	IEC0bits.U1TXIE = 1;				// Enable UART1 TX interrupt
//	compkey.Byte = 0;
//	arg[0].p_arg = USR_NULL;
//	arg[1].p_arg = USR_NULL;
//	arg[2].p_arg = USR_NULL;
//	arg[3].p_arg = USR_NULL;
//	arg[4].p_arg = USR_NULL;
//	while(1){
//		echo_str("\x055\x055\x055\x055\x055\x055\x055\x055\x055\x055", 10);
//		OSTimeDlyHMSM(0, 0, 1, 0);
//	}
//	consol_q = OSQCreate(&msg_q[0], MSG_QUEUE_SZ);
	pCmdCur = CmdBuf;
	echo_str("\r\n>>> ", 6);
	while(USR_TRUE){
		ret_ctr = FIFO_Read(U1RxBuf, U1R_BUF_LEN);
		if(ret_ctr > 0){
//		if(FIFO_Read(U1RxBuf, U1R_BUF_LEN) > 0){
			ArrangeCMD(ret_ctr);
		}
		// task shedule
		OS_Sched();
	}
}

/*********************************************************************
 * Name        : static void ArrangeCMD(USR_INT16S lCtr)
 * Function    : analyze the cmd string readed from uart buffer
 * PreCondition: None
 * Input       : lCtr the string length
 * Output      : None
 * Side Effects: None
 * Author      : Lau
 * Time/Creat  : 15:50 7/8/2014
 * Time/Modify : 15:50 7/8/2014
 * Note        : None
 ********************************************************************/
static void ArrangeCMD(USR_INT16S lCtr)
{
	USR_INT08U *tPtr = U1RxBuf;
	USR_INT08U tdif;
	while(lCtr > 0){
		if(*tPtr == CR_R_CHAR){
			// Execute the CMD
			if(CmdSize > 0){
				CmdBuf[CmdSize] = '\0';
//				ExecCmd();
				OSQPost(consol_q, CmdBuf);
				pCmdCur = CmdBuf;
				CmdSize = 0;
			}
			else{
				echo_str("\r\n>>> ", 6);
			}
		}
		else{
			if(compkey._1B){
				if(compkey._5B){
					if(*tPtr == CMPL_R_CHAR){			// Right Key pressed
						if(pCmdCur - CmdBuf > 1){
							echo_char(BS_CHAR);
							pCmdCur --;
						}
					}
					else if(*tPtr == CMPL_L_CHAR){		// Left Key pressed
						if((pCmdCur - CmdBuf) < CmdSize){
							echo_char(*pCmdCur);
							pCmdCur ++;
						}
					}
					compkey._1B = 0;
					compkey._5B = 0;
				}
				else{
					if(*tPtr == CMPL_CHAR){
						compkey._5B = 1;
					}
					else{compkey._1B = 0;}
				}
			}
			else if(*tPtr > US_CHAR && *tPtr < DEL_CHAR){
				// ECHO back
				if(CmdSize < CMD_MAX_LEN){				// Valid char & echo the char
					echo_char(*tPtr);
					tdif = CmdBuf + CmdSize - pCmdCur;
					if(tdif > 0){
						echo_str(pCmdCur, tdif);
						mov_block_r(pCmdCur);
						while(tdif-- > 0){
							echo_char(BS_CHAR);
						}
					}
					*pCmdCur++ = *tPtr++;				// Insert a data to cmdbuf
					CmdSize ++;
				}
				else{									// Bad cmd echo and clear the cmdbuf
					pCmdCur = CmdBuf;
					CmdSize = 0;
				}
			}
			if(*tPtr == BS_CHAR){					// Delete the char before cursor
				if(CmdSize > 0){
					tdif = CmdBuf + CmdSize - pCmdCur;
					echo_char(BS_CHAR);
					echo_str(pCmdCur, tdif);
					echo_char(ESC_CHAR);
					echo_char(CMPL_CHAR);
					echo_char('\x4A');
					if(tdif > 0){
						while(tdif-- > 0){
							echo_char(BS_CHAR);
						}
						mov_block_l(pCmdCur);
					}
					pCmdCur --;
					CmdSize --;
				}
			}
			if(*tPtr == DEL_CHAR){						// Delete the char after cursor
				
			}
			if(*tPtr == ESC_CHAR){						// Complex key
				compkey._1B = 1;
			}
			else{										// Ignore illegal char
				*tPtr ++;
			}
		}
		lCtr --;										// Pointer to the next char
	}
}



/*********************************************************************
 * Name        : void _ISR _U1RXInterrupt(void)
 * Function    : uart1 rx interrupt handler
 * PreCondition: None
 * Input       : None
 * Output      : None
 * Side Effects: None
 * Author      : Lau
 * Time/Creat  : 15:50 7/8/2014
 * Time/Modify : 15:50 7/8/2014
 * Note        : None
 ********************************************************************/
/*
void _ISR _U1RXInterrupt(void)//_ISR
{	
	OSIntNesting ++;
	IFS0bits.U1RXIF = 0;
//	if(U1STAbits.OERR){
		U1STAbits.OERR = 0;
//	}
	
	INTE_WR_FIFO();				// put the data to fifo buffer
	OSIntNesting --;
}

void _ISR _U1TXInterrupt(void)
{
	
}
*/


static void mov_block_r(USR_INT08U *lcur)
{
	USR_INT08U *tend = CmdBuf + CmdSize - 1;
	USR_INT08U *tbf = tend - 1;
	
	while(tend != lcur){
		*tend-- = *tbf--;
	}
}

static void mov_block_l(USR_INT08U *lcur)
{
	USR_INT08U *tend = CmdBuf + CmdSize - 1;
	USR_INT08U *tnxt = lcur + 1;
	
	while(tend != tnxt){
		*lcur++ = *tnxt++;
	}
}
